package com.moli.iov.sys.remote.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.moli.iov.exception.BusinessException;
import com.moli.iov.model.dto.req.PageExtend;
import com.moli.iov.notify.model.dto.ResetPwdSmsDto;
import com.moli.iov.notify.model.dto.SaveUserMailAndSmsDto;
import com.moli.iov.notify.remote.IMailRemoteService;
import com.moli.iov.notify.remote.ISmsRemoteService;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.sys.constants.Constant;
import com.moli.iov.sys.enums.CompanyStatusEnum;
import com.moli.iov.sys.enums.RoleStatusEnum;
import com.moli.iov.sys.enums.SuperAdminEnum;
import com.moli.iov.sys.enums.UserStatusEnum;
import com.moli.iov.sys.enums.UserTypeEnum;
import com.moli.iov.sys.model.dto.req.CompanyDto;
import com.moli.iov.sys.model.dto.req.PwdDto;
import com.moli.iov.sys.model.dto.req.UserDto;
import com.moli.iov.sys.model.po.Company;
import com.moli.iov.sys.model.po.Role;
import com.moli.iov.sys.model.po.User;
import com.moli.iov.sys.model.po.UserRole;
import com.moli.iov.sys.remote.IUserRemoteService;
import com.moli.iov.sys.service.ICompanyService;
import com.moli.iov.sys.service.IRoleService;
import com.moli.iov.sys.service.IUserRoleService;
import com.moli.iov.sys.service.IUserService;
import com.moli.iov.sys.utils.PwdUtil;
import com.moli.iov.third.model.dto.op.CreateUserDto;
import com.moli.iov.third.model.dto.op.ModifyPasswordDto;
import com.moli.iov.third.model.dto.op.ModifyUserDto;
import com.moli.iov.third.remote.IUserOpRemoteService;
import com.moli.iov.util.CommonUtils;
import com.moli.iov.util.ValidationUtils;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 *  用户业务
 * </p>
 *
 * @author zql
 * @since 2019/9/9 11:40
 */
@Slf4j
@Service(group = "${service.group}")
public class UserRemoteServiceImpl implements IUserRemoteService {

  @Autowired
  private IUserService userService;

  @Autowired
  private ICompanyService companyService;

  @Autowired
  private IUserRoleService userRoleService;

  @Autowired
  private IRoleService roleService;

  @Reference(group = "${service.group}", check = false)
  private IMailRemoteService mailRemoteService;

  @Reference(group = "${service.group}", check = false)
  private ISmsRemoteService smsRemoteService;

  @Reference(group = "${service.group}", check = false)
  private IUserOpRemoteService userOpRemoteService;

  @Value("${pwd.salt}")
  private String salt;

  @Value("${op.companyId}")
  private Long opCompanyId;

  @Value("${pwd.prefix}")
  private String pwdPrefix;

  /**
   * 分页查询用户列表
   * @param userDto
   * @return
   */
  @Override
  public RestResponse<PageExtend<User>> listUserOfPage(UserDto userDto) {
    return RestResponse.success(userService.listUserOfPage(userDto));
  }

  @Override
  public RestResponse<List<User>> findByUserIdList(List<Long> userIdList){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.in("user_id", userIdList);
    return RestResponse.success(userService.list(queryWrapper));
  }

  /**
   * 获取单个用户
   * @param account
   * @return
   */
  @Override
  public RestResponse<User> getUserByAccount(String account) {
    UserDto userDto = new UserDto();
    userDto.setAccount(account);
    List<User> users = userService.listUsers(userDto);
    if(users == null || users.isEmpty() || users.get(0) == null){
      return RestResponse.failure("账号不存在");
    }
    return RestResponse.success(users.get(0));
  }

  /**
   * 添加用户
   * @param userDto
   * @return
   */
  @Transactional
  @Override
  public RestResponse saveUser(UserDto userDto) {

    validOfSave(userDto);

    PwdDto pwdDto = PwdUtil.createPassword(salt);
    userDto.setPassword(pwdDto.getEnPassword());

    User user = userService.saveUser(assembleUser(userDto));
    if(user.getUserId() == null){
      return RestResponse.failure("添加用户失败");
    }

    boolean isT = userRoleService.setUserRole(new UserRole(userDto.getRoleId(), user.getUserId()));
    if(!isT){
      throw new BusinessException("添加用户失败");
    }

    log.info("添加用户密码信息：{}", pwdDto);

    if(opCompanyId != null && opCompanyId.equals(user.getCompanyId())){
      log.info("添加茉莉科技用户 调用通知OP服务 用户：{}", user);
      user.setRoleId(userDto.getRoleId());
      user.setRealName(userDto.getRealName());
      saveUserSyncOp(user);
    }

    //向用户进行短信与邮箱推送
    sendMailAndSmsOfSaveUser(userDto, pwdDto.getPassword());

    return RestResponse.success();
  }

  /**
   * 添加用户同步OP
   * @param user
   */
  private void saveUserSyncOp(User user){

    CreateUserDto userDto = new CreateUserDto();
    CommonUtils.copyProperties(user, userDto);
    userDto.setIovGroupId(user.getRoleId());
    userDto.setIovGroupName(user.getRoleName());
    RestResponse restRe = RestResponse.success();
    try {
      restRe = userOpRemoteService.createUser(userDto);
    } catch (Exception e) {
      log.info("添加用户同步OP异常", e);
      throw new BusinessException("添加用户同步OP失败");
    }

    if(!restRe.flag){
      throw new BusinessException(restRe.getMessage());
    }
  }

  /**
   * 组装用户实体
   * @param userDto
   * @return
   */
  private User assembleUser(UserDto userDto){
    User user = new User();
    CommonUtils.copyProperties(userDto, user);
    user.setAccount(user.getEmail());
    return user;
  }

  /**
   * 添加用户发送邮件、短信
   */
  @Async
  public void sendMailAndSmsOfSaveUser(UserDto userDto, String pwd){
    SaveUserMailAndSmsDto saveUserMailAndSmsDto = new SaveUserMailAndSmsDto();
    CommonUtils.copyProperties(userDto, saveUserMailAndSmsDto);
    saveUserMailAndSmsDto.setPassword(pwd);
    saveUserMailAndSmsDto.setAccount(userDto.getEmail());
    log.info("添加用户发送邮件、短信 userDto:{} saveUserMailAndSmsDto：{}",
        userDto, saveUserMailAndSmsDto);
    mailRemoteService.sendMailAndSmsOfSaveUser(saveUserMailAndSmsDto);
  }

  /**
   * 修改用户
   * @param userDto
   * @return
   */
  @Transactional
  @Override
  public RestResponse updateUser(UserDto userDto) {

    validOfUpdateUser(userDto);

    User user = new User();
    CommonUtils.copyProperties(userDto, user);
    boolean isT = userService.updateUser(user);
    if(!isT){
      return RestResponse.failure("修改用户失败");
    }

    isT = userRoleService.setUserRole(new UserRole(userDto.getRoleId(), userDto.getUserId()));
    if(!isT){
      throw new BusinessException("修改用户失败");
    }

    if(opCompanyId != null &&
        (opCompanyId.equals(userDto.getSysCompanyId()) || opCompanyId.equals(userDto.getCompanyId()))){
      User byId = userService.getById(userDto.getUserId());
      byId.setRoleId(userDto.getRoleId());
      byId.setRoleName(userDto.getRoleName());
      updateUserSyncOp(byId);
    }

    return RestResponse.success();
  }


  /**
   * 修改用户同步OP
   * @param user
   */
  private void updateUserSyncOp(User user){

    ModifyUserDto userDto = new ModifyUserDto();
    CommonUtils.copyProperties(user, userDto);
    userDto.setIovGroupId(user.getRoleId());
    userDto.setIovGroupName(user.getRoleName());
    RestResponse restRe = RestResponse.success();
    try {
      restRe = userOpRemoteService.modifyUser(userDto);
    } catch (Exception e) {
      throw new BusinessException("修改用户同步OP失败");
    }

    if(!restRe.flag){
      throw new BusinessException(restRe.getMessage());
    }
  }
  /**
   * 重置密码
   * @param userDto
   * @return
   */
  @Transactional
  @Override
  public RestResponse resetPwd(UserDto userDto) {

    User user = validOfResetPwd(userDto);

    PwdDto pwdDto = PwdUtil.createPassword(salt);
    userDto.setEmail(user.getEmail());
    userDto.setPassword(pwdDto.getEnPassword());
    user.setPassword(userDto.getPassword());

    boolean isT = userService.updateUser(user);
    if(!isT){
      return RestResponse.failure("重置密码失败");
    }

    if(opCompanyId != null && opCompanyId.equals(user.getCompanyId())){
      resetPwdSyncOp(user.getEmail(), pwdDto.getEnPassword());
    }

    //发送通知短信
    sendSmsOfResetPwd(user, pwdDto.getPassword());

    return RestResponse.success();
  }

  /**
   * 重置密码同步OP
   * @param account
   * @param password
   */
  private void resetPwdSyncOp(String account, String password){
    ModifyPasswordDto modifyPasswordDto = new ModifyPasswordDto();
    modifyPasswordDto.setAccount(account);
    modifyPasswordDto.setPassword(password);
    RestResponse restRe = RestResponse.success();
    try {
      restRe = userOpRemoteService.resetPassword(modifyPasswordDto);

    } catch (Exception e) {
      throw new BusinessException("重置密码同步OP失败");
    }

    if(!restRe.flag){
      throw new BusinessException(restRe.getMessage());
    }
  }


  /**
   * 重置密码发送短信
   * @param user
   * @param beforePwd
   */
  @Async
  public void sendSmsOfResetPwd(User user, String beforePwd){
    ResetPwdSmsDto resetPwdSmsDto = new ResetPwdSmsDto();
    resetPwdSmsDto.setMobile(user.getUserPhone());
    resetPwdSmsDto.setEmail(user.getEmail());
    resetPwdSmsDto.setPassword(beforePwd);
    smsRemoteService.sendSmsOfResetPwd(resetPwdSmsDto);
  }

  /**
   * 重置密码校验
   * @param userDto
   * @return
   */
  private User validOfResetPwd(UserDto userDto){
    if(userDto == null || userDto.getUserId() == null){
      throw new BusinessException("用户id不能为空");
    }

    User user = userService.getUserByUserId(userDto.getUserId());
    if(user == null){
      throw new BusinessException("用户id不能存在");
    }

    if(userDto.getSysUserType() == UserTypeEnum.COMPANY.getFlag() &&
        !userDto.getSysCompanyId().equals(user.getCompanyId())){
      throw new BusinessException("当前操作员无修改此用户权限");
    }

    return user;
  }

  /**
   * 添加 校验
   * @param userDto
   * @return
   */
  private void validOfSave(UserDto userDto){

    ValidationUtils.restResponseValidate(userDto, UserDto.Save.class);

    Role roleByRoleId = roleService.getRoleByRoleId(userDto.getRoleId());
    if(roleByRoleId == null){
      throw new BusinessException("角色id不存在");
    }

    if(RoleStatusEnum.DISABLED.getFlag() == roleByRoleId.getStatus()){
      throw new BusinessException("角色已停用");
    }

    userDto.setRoleName(roleByRoleId.getRoleName());

    if(userDto.getCompanyId() != null){
      Company company1 = companyValid(userDto.getCompanyId());
      userDto.setCompanyName(company1.getCompanyName());
    }

    UserDto userDtoQuery = new UserDto();
    userDtoQuery.setUserPhone(userDto.getUserPhone());
    List<User> users = userService.listUsers(userDtoQuery);
    if(users != null && !users.isEmpty()){
      throw new BusinessException("手机号已经存在");
    }

    userDtoQuery = new UserDto();
    userDtoQuery.setEmail(userDto.getEmail());
    users = userService.listUsers(userDtoQuery);
    if(users != null && !users.isEmpty()){
      throw new BusinessException("邮箱已经存在");
    }
  }

  /**
   * 校验企业
   * @param companyId
   * @return
   */
  private Company companyValid(Long companyId){
    Company company = companyService.getById(companyId);
    if(company == null){
      throw new BusinessException("企业id不存在");
    }

    if(company.getStatus() == CompanyStatusEnum.DISABLED.getFlag()){
      throw new BusinessException("企业已停用");
    }

    return company;
  }

  /**
   * 修改用户 校验
   * @param userDto
   * @return
   */
  private void validOfUpdateUser(UserDto userDto){

    ValidationUtils.restResponseValidate(userDto, UserDto.Update.class);

    User userByUserId = userService.getUserByUserId(userDto.getUserId());
    if(userByUserId == null){
      throw new BusinessException("用户id不能存在");
    }

    if(userDto.getSysUserType() == UserTypeEnum.COMPANY.getFlag() &&
       !userDto.getSysCompanyId().equals(userByUserId.getCompanyId())){
      throw new BusinessException("当前操作员无修改此用户权限");
    }

    Role roleByRoleId = roleService.getRoleByRoleId(userDto.getRoleId());
    if(roleByRoleId == null){
      throw new BusinessException("角色id不存在");
    }

    if(RoleStatusEnum.DISABLED.getFlag() == roleByRoleId.getStatus()){
      throw new BusinessException("角色已停用");
    }
    userDto.setRoleName(roleByRoleId.getRoleName());

    if(userDto.getCompanyId() != null){
      CompanyDto companyDto = new CompanyDto();
      companyDto.setCompanyId(userDto.getCompanyId());
      List<Company> companies = companyService.listCompany(companyDto);
      if(companies == null || companies.isEmpty()){
        throw new BusinessException("企业id不存在");
      }

      Company company = companies.get(0);
      if(company.getStatus() == CompanyStatusEnum.DISABLED.getFlag()){
        throw new BusinessException("企业已停用");
      }
    }

    UserDto userDtoQuery = new UserDto();
    userDtoQuery.setUserPhone(userDto.getUserPhone());
    userDtoQuery.setNeUserId(userDto.getUserId());

    List<User> users = userService.listUsers(userDtoQuery);
    if(users != null && !users.isEmpty()){
      throw new BusinessException("手机号已经存在");
    }
  }

  /**
   * 创建企业超级管理员
   * @param companyDto
   * @return
   */
  @Async
  @Override
  public RestResponse saveSuperAdminOfCompany(CompanyDto companyDto) {

    UserDto userDto = assembleSuperAdmin(companyDto);

    PwdDto pwdDto = PwdUtil.createPassword(salt);
    userDto.setPassword(pwdDto.getEnPassword());

    User user = userService.saveUser(assembleUser(userDto));
    if(user.getUserId() == null){
      log.error("创建管理员失败");
      return RestResponse.failure("创建管理失败");
    }

    //向用户进行短信与邮箱推送
    sendMailAndSmsOfSaveUser(userDto, pwdDto.getPassword());
    return RestResponse.success();
  }

  /**
   * 组装管理员用户
   * @param companyDto
   * @return
   */
  private UserDto assembleSuperAdmin(CompanyDto companyDto){
    UserDto userDto = new UserDto();
    userDto.setCompanyId(companyDto.getCompanyId());
    userDto.setCompanyName(companyDto.getCompanyName());
    userDto.setEmail(companyDto.getEmail());
    userDto.setAccount(companyDto.getEmail());
    userDto.setRealName(Constant.SUPER_ADMIN_ROLE_NAME);
    userDto.setStatus(UserStatusEnum.ENABLED.getFlag());
    userDto.setUserPhone(companyDto.getCorporationPhone());
    userDto.setUserType(UserTypeEnum.COMPANY.getFlag());
    userDto.setIsSuperAdmin(SuperAdminEnum.YES.getFlag());
    userDto.setOperatorId(companyDto.getSysUserId());
    userDto.setOperatorName(companyDto.getSysRealName());
    return userDto;
  }

  /**
   * 修改密码
   * @param userDto
   * @return
   */
  @Transactional
  @Override
  public RestResponse updatePwd(UserDto userDto) {

    User user = updatePwdValid(userDto);

    String pwd = PwdUtil.createPwd(userDto.getNewPassword(), salt);
    user.setPassword(pwd);

    if(!userService.updateUser(user)){
      return RestResponse.failure("修改密码失败");
    }

    if(opCompanyId != null && opCompanyId.equals(user.getCompanyId())){
      updatePwdSyncOp(user.getEmail(), pwd);
    }

    return RestResponse.success();
  }

  /**
   * 修改密码同步OP
   * @param account
   * @param password
   */
  @Async
  public void updatePwdSyncOp(String account, String password){
    ModifyPasswordDto modifyPasswordDto = new ModifyPasswordDto();
    modifyPasswordDto.setAccount(account);
    modifyPasswordDto.setPassword(password);
    RestResponse restRe = RestResponse.success();
    try {
      restRe = userOpRemoteService.modifyPassword(modifyPasswordDto);

    } catch (Exception e) {
      throw new BusinessException("修改密码同步OP失败");
    }

    if(!restRe.flag){
      throw new BusinessException(restRe.getMessage());
    }
  }

  /**
   * 修改密码校验
   * @param userDto
   * @return
   */
  private User updatePwdValid(UserDto userDto){

    if(userDto.getOldPassword().length() <= pwdPrefix.length()) {
      throw new BusinessException("原密码输入错误");
    }

    if(userDto.getNewPassword().length() <= pwdPrefix.length()){
      throw new BusinessException("新密码格式错误");
    }

    userDto.setOldPassword(PwdUtil.decodePwd(pwdPrefix, userDto.getOldPassword()));
    userDto.setNewPassword(PwdUtil.decodePwd(pwdPrefix, userDto.getNewPassword()));

    User user = userService.getUserByUserId(userDto.getUserId());
    if(user == null){
      throw new BusinessException("用户id不存在");
    }

    if(UserStatusEnum.DISABLED.getFlag() == user.getStatus()){
      throw new BusinessException("用户已停用");
    }


    String oldPwd = PwdUtil.createPwd(userDto.getOldPassword(), salt);
    if(!user.getPassword().equals(oldPwd)){
      throw new BusinessException("原密码输入错误");
    }

    return user;
  }

  /**
   * 根据角色id查询 用户列表
   * @param userDto
   * @return
   */
  @Override
  public RestResponse<List<User>> listUsersByRoleId(UserDto userDto) {

    List<Long> userIds = userRoleService.listUserIdByRoleId(userDto.getRoleId());
    if(userIds == null || userIds.isEmpty()){
      return RestResponse.failure("角色未分配用户");
    }
    userDto.setUserIds(userIds);
    List<User> users = userService.listUsers(userDto);
    return RestResponse.success(users);
  }
}
